module Ministerio (Ministerio, agregarHotelM, secretariasM, registroM, nuevoM, cadenasDeHotelesM, cadenasAmarretasM, fusionAutorizadaM) where

import Tipos
import Reserva
import Habitacion
import Hotel

data Ministerio = REG Provincia Hotel Ministerio | MT [Provincia] deriving (Show)

nuevoM :: [Provincia] -> Ministerio
nuevoM ps = MT ps

secretariasM :: Ministerio -> [Provincia]
secretariasM (MT ps) = ps
secretariasM (REG _ _ m) = secretariasM m

registroM :: Ministerio -> Provincia -> [Hotel]
registroM (MT pv) p = []
registroM (REG prov ht m) p
  | prov == p = ht:(registroM m p)
  | otherwise = registroM m p

cadenasDeHotelesM :: Ministerio -> [[Hotel]]
cadenasDeHotelesM (MT ps) = [[]]
cadenasDeHotelesM m = cadenasDeHotelesAux m (sacarRepetidos (listaCadenasAux m))

agregarHotelM :: Ministerio -> Hotel -> Provincia -> Ministerio
agregarHotelM m h p = REG p h m 

cadenasAmarretasM :: Ministerio -> [Cadena]
cadenasAmarretasM m = cadenasQueEstanEnMenosProvincias m

fusionAutorizadaM :: Ministerio -> Cadena -> Cadena -> Ministerio
fusionAutorizadaM (MT ps) _ _ = MT ps
fusionAutorizadaM (REG p h m) c1 c2
  | cadenaH h == c2 = REG p (venderH h c1) (fusionAutorizadaM m c1 c2)
  | otherwise = REG p h (fusionAutorizadaM m c1 c2)

----------------
-- Auxiliares --
----------------

-- cadenasDeHotelesM --

cadenasDeHotelesAux :: Ministerio -> [Cadena] -> [[Hotel]]
cadenasDeHotelesAux m (x:[]) = [hotelesDeCadena m x]
cadenasDeHotelesAux m (x:xs) = (hotelesDeCadena m x):(cadenasDeHotelesAux m xs)

listaCadenas :: Ministerio -> [Cadena]
listaCadenas h = sacarRepetidos (listaCadenasAux h)

sacarRepetidos :: [Cadena] -> [Cadena]
sacarRepetidos (x:[]) = [x]
sacarRepetidos (x:xs)
  | elem x xs = sacarRepetidos xs
  | otherwise = x:(sacarRepetidos xs)

listaCadenasAux :: Ministerio -> [Cadena]
listaCadenasAux (MT p) = []
listaCadenasAux (REG _ h m) = (cadenaH h):(listaCadenasAux m)

hotelesDeCadena:: Ministerio -> Cadena -> [Hotel]
hotelesDeCadena (MT p) c = []
hotelesDeCadena (REG p h m) c
  | cadenaH h == c = h:(hotelesDeCadena m c)
  | otherwise = hotelesDeCadena m c

-- cadenasAmarretasM --

cadenasQueEstanEnMenosProvincias :: Ministerio -> [Cadena]
cadenasQueEstanEnMenosProvincias m = dameCadenasConPresencia (todasLasCadenas m) (cantMinima (todasLasCadenas m) m) m

todasLasCadenas :: Ministerio -> [Cadena]
todasLasCadenas m = aplanarCadenas (cadenasDeHotelesM m)

aplanarCadenas :: [[Hotel]] -> [Cadena]
aplanarCadenas (hs:[]) = [cadenaH (hs !! 0)]
aplanarCadenas (hs:hss) = (cadenaH (hs !! 0)) : (aplanarCadenas hss)

dameCadenasConPresencia :: [Cadena] -> Int -> Ministerio -> [Cadena]
dameCadenasConPresencia (c:[]) n m = if (presencia c m) == n then [c] else []
dameCadenasConPresencia (c:cs) n m = if (presencia c m) == n then [c] ++ (dameCadenasConPresencia cs n m) else dameCadenasConPresencia cs n m

cantMinima :: [Cadena] -> Ministerio -> Int
cantMinima (c:[]) m = presencia c m
cantMinima (c:cs) m = if (presencia c m) < (cantMinima cs m) then presencia c m else cantMinima cs m 

presencia :: Cadena -> Ministerio -> Int
presencia c m = enCuantasProvinciasEsta c m (secretariasM m)

enCuantasProvinciasEsta :: Cadena -> Ministerio -> [Provincia] -> Int
enCuantasProvinciasEsta c m (p:[]) = if (estaCadena c (registroM m p)) then 1 else 0
enCuantasProvinciasEsta c m (p:ps) = (if (estaCadena c (registroM m p)) then 1 else 0) + (enCuantasProvinciasEsta c m ps)

estaCadena :: Cadena -> [Hotel] -> Bool
estaCadena c (h:[]) = (cadenaH h) == c
estaCadena c (h:hs) = (cadenaH h) == c || (estaCadena c hs)

-- fusionAutorizadaM --

accesorios :: Hotel -> [(Accesorio, Dinero)]
accesorios h = [(Jacuzzi, precioAccesorioH h Jacuzzi), (LCD, precioAccesorioH h LCD), (PS3, precioAccesorioH h PS3), (DVD, precioAccesorioH h DVD), (Pelotero, precioAccesorioH h Pelotero), (Inflable, precioAccesorioH h Inflable)]

tiposDeHabitaciones :: Hotel -> [(TipoHabitacion, Dinero)]
tiposDeHabitaciones h = [(Simple, tarifaXDiaH h Simple), (Doble, tarifaXDiaH h Doble), (Triple, tarifaXDiaH h Triple), (Cuadruple, tarifaXDiaH h Cuadruple)]

provinciaDeHotel :: Hotel -> Ministerio -> Provincia
provinciaDeHotel h m = buscarEnProvincias h (secretariasM m) m

buscarEnProvincias :: Hotel -> [Provincia] -> Ministerio -> Provincia
buscarEnProvincias h (p:[]) m = p
buscarEnProvincias h (p:ps) m 
  | elem h (registroM m p) = p
  | otherwise = buscarEnProvincias h ps m

